//
//  JJInfiniteTableView.m
//  TableViewInfinite
//
//  Created by jxf on 16/2/21.
//  Copyright © 2016年 JJ.sevn. All rights reserved.
//

#import "JJInfiniteTableView.h"
#import "UIView+AdjustFrame.h"

@interface JJInfiniteTableView ()<UIScrollViewDelegate, UITableViewDataSource, UITableViewDelegate>
@property(nonatomic, weak) UIScrollView * scrollView;
@property(nonatomic, weak) JJInfiniteTitleBar * titleBar;
@property(nonatomic, strong) NSMutableDictionary * tableViewMemoryContentOffset;
@property(nonatomic, weak) UIView * leftDrawerView;
@property(nonatomic, weak) UIView * rightDrawerView;

@end

@implementation JJInfiniteTableView
#pragma mark ------------------------------------------
#pragma mark init
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        UIScrollView *scrollView = [[UIScrollView alloc] init];
        scrollView.showsHorizontalScrollIndicator = NO;
        scrollView.showsVerticalScrollIndicator = NO;
        scrollView.bounces = NO;
        scrollView.pagingEnabled = YES;
        scrollView.delegate = self;
        [self addSubview:scrollView];
        self.scrollView = scrollView;
        
        for (int i = 0; i < 3; i++) {
            UITableView *tableView = [[UITableView alloc] init];
            tableView.delegate = self;
            tableView.dataSource = self;
            tableView.tag = i;
            [scrollView addSubview:tableView];
        }
        JJInfiniteTitleBar *titleBar = [[JJInfiniteTitleBar alloc] init];
        [self insertSubview:titleBar aboveSubview:self.scrollView];
        self.titleBar = titleBar;
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(titleBtnDidClicked) name:JJInfiniteTitleBarBtnDidClicked object:nil];
    }
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:JJInfiniteTitleBarBtnDidClicked object:nil];
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.scrollView.frame = self.bounds;
    self.scrollView.contentSize = CGSizeMake(self.jj_width * self.scrollView.subviews.count, 0);
    //titleBar
    if (!self.titleBarHeight) {
        self.titleBarHeight = 35;
    }
    self.titleBar.frame = CGRectMake(0, 0, self.jj_width, self.titleBarHeight);
    // tableView
    NSInteger index = 0;
    for (UITableView *tableView in self.scrollView.subviews) {
        tableView.frame = CGRectMake(self.jj_width * index, 0, self.jj_width, self.jj_height);
        // 为什么我这里设置 contentInset, tableView并没有自动向下偏移(contentInset 打印结果显示已经设置了 contentInset 了), 这里我手动让他向下滚了一个 titleBar 的高度, 不是应该跟着滚得嘛?!
        tableView.contentInset = UIEdgeInsetsMake(self.titleBar.frame.size.height, 0, 0, 0);
        tableView.contentOffset = CGPointMake(0, -self.titleBar.frame.size.height);
        tableView.scrollIndicatorInsets = tableView.contentInset;
        index ++;
    }
    
    [self reloadSelf];
}

#pragma mark ------------------------------------------
#pragma mark UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    // 处理标题跟随 drawerView
    if (self.scrollView.contentOffset.x < 0) {
        self.titleBar.jj_x = -self.scrollView.contentOffset.x;
    }
    // 处理 rightDrawerView 进入跟随
    if (self.scrollView.contentOffset.x > self.jj_width * 2){
        CGFloat x = self.scrollView.contentSize.width - self.scrollView.contentOffset.x;
        self.rightDrawerView.frame = CGRectMake(x, 0, self.rightDrawerView.jj_width, self.rightDrawerView.jj_height);
        self.titleBar.jj_x = -(self.frame.size.width - x);
    }
    if (self.scrollView.contentOffset.x > 0 && self.scrollView.contentOffset.x < self.jj_width * 2) {
        self.titleBar.jj_x = 0;
    }
    if (![scrollView isKindOfClass:[UITableView class]]) {

        UITableView *curTableView = nil;
        CGFloat curTableViewMargin = MAXFLOAT;
        for (UITableView *tableView in self.scrollView.subviews) {
            CGFloat margin = ABS(tableView.jj_x - scrollView.contentOffset.x);
            if (margin < curTableViewMargin) {
                curTableViewMargin = margin;
                curTableView = tableView;
            }
        }
        self.titleBar.currentPage = curTableView.tag;
    }
//    NSLog(@"%f", self.scrollView.contentOffset.x);
    
}

-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    // 坑, 防止在抽屉界面, 快速滑动导致 scrollView 飞滚(因为这时, pageEnable == NO)...好坑...我目前的做法只能保证手指飞滚的情况下,不会乱跳了,如果大力瞬间滑动的话, 还是会滑到第1页, 第二页,这时候页面会有小 bug(有谁有更好的做法告诉我)
    if (velocity.x > 0 && self.scrollView.contentOffset.x < 0) { //当发现向左滚动时候, 设置pagingEnabled yes
        self.scrollView.pagingEnabled = YES;
    }
    if (velocity.x < 0 && self.scrollView.contentOffset.x > self.jj_width * 2) {
        self.scrollView.pagingEnabled = YES;
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self dealWhenScrollViewEndDraggingOrEndDecelerate:scrollView];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    // 处理分页功能pagingEnabled和抽屉 view 的细节
    if (self.scrollView.contentOffset.x < 0) {
        if (self.scrollView.contentOffset.x <= -self.scrollView.contentInset.left * 0.5) {
            self.scrollView.pagingEnabled = NO;
            [self.scrollView setContentOffset:CGPointMake(-self.scrollView.contentInset.left, 0) animated:YES];
            // 加一个蒙版
            [self addHudOnScrollView];
//            self.scrollView.userInteractionEnabled = NO;
        }else{
            [self.scrollView setContentOffset:CGPointZero animated:YES];
            self.scrollView.pagingEnabled = YES;
        }
    }
    if (self.scrollView.contentOffset.x > self.jj_width * 2) {
        if (self.scrollView.contentOffset.x >= self.scrollView.contentInset.right * 0.5 + self.jj_width * 2) {
            self.scrollView.pagingEnabled = NO;
            [self.scrollView setContentOffset:CGPointMake(self.scrollView.contentInset.right + self.jj_width * 2, 0) animated:YES];
        }else{
            self.scrollView.pagingEnabled = YES;
            [self.scrollView setContentOffset:CGPointMake(self.jj_width * 2, 0) animated:YES];
        }
    }
    if (!decelerate) {
        self.scrollView.pagingEnabled = YES;
    }
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
    if (self.scrollView.contentOffset.x > 0 && self.scrollView.contentOffset.x < self.jj_width * 2) {
        self.scrollView.pagingEnabled  = YES;
    }
}

#pragma mark ------------------------------------------
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.dataSource infiniteTableView:self numberOfCellsAtIndexPart:tableView.tag];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.dataSource infiniteTableView:self andTableView:tableView cellForRowAtIndexPath:indexPath andItemIndex:tableView.tag];
    return cell;
}

#pragma mark ------------------------------------------
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self.delegate respondsToSelector:@selector(infiniteTableView:didSelectedRowAtIndexPath:)]) {
        [self.delegate infiniteTableView:self didSelectedRowAtIndexPath:indexPath];
    }
}

#pragma mark ------------------------------------------
#pragma mark other
- (void)dealWhenScrollViewEndDraggingOrEndDecelerate:(UIScrollView *)scrollView
{
    if ([scrollView isKindOfClass:[UITableView class]]) {
        // 记录 tableView 的偏移量
        NSString *key = [NSString stringWithFormat:@"%zd", self.titleBar.currentPage];
        self.tableViewMemoryContentOffset[key] =[NSValue valueWithCGPoint:scrollView.contentOffset];
        return;
    }else{
        // drawerView 的时候,不要 reload
        if (self.scrollView.contentOffset.x < 0){
            return;
        };
        if (self.scrollView.contentOffset.x >self.jj_width * 2) {
            return;
        }
        [self reloadSelf];
    }
}

- (void)reloadSelf
{
    // closeInfiniteView状态下, 处理特殊情况:第一个和最后一个 tableView, 同时设置 drawerView
    if (self.closeInfiniteView)
    {
        if (self.titleBar.currentPage == 0)
        {
            [self setupLeftForFirst];
            [self setupLeftDrawerView];
            return;
        }
        if (self.titleBar.currentPage == self.titleBar.numberOfPages - 1)
        {
            [self setupRightForLast];
            [self setupRightDrawerView];
            return;
        }
    }
    
    NSInteger itemsCount = [self.dataSource numberOfItemsAtInfiniteTableView:self];
    self.titleBar.numberOfPages = itemsCount;
    NSInteger curPage = self.titleBar.currentPage;
    for (int i = 0; i < self.scrollView.subviews.count; i++) {
        UITableView *tableView = self.scrollView.subviews[i];
        NSInteger tableViewIndex = 0;
        if (i == 1) {
            tableViewIndex = curPage;
        }else if (i == 0){
            tableViewIndex = curPage - 1;
        }else{
            tableViewIndex = curPage + 1;
        }
        
        if (tableViewIndex == -1) {
            tableViewIndex = self.titleBar.numberOfPages - 1;
        }else if (tableViewIndex == self.titleBar.numberOfPages){
            tableViewIndex = 0;
        }
        tableView.tag = tableViewIndex;
        [tableView reloadData];
        // 还原tableView原来的偏移量
        NSString *key = [NSString stringWithFormat:@"%zd", tableViewIndex];
        CGPoint oriPoint = [self.tableViewMemoryContentOffset[key] CGPointValue];
        // 这一步是解决设置 contentInset 没效果的 bug, 我也不知道为什么...(看60行)
        if (oriPoint.y == 0) {
            oriPoint =  CGPointMake(0, -self.titleBar.frame.size.height);
        }
        tableView.contentOffset = oriPoint;
    }
    // 重置 scrollView 的 contentOffset
    self.scrollView.contentOffset = CGPointMake(self.jj_width, 0);
}

- (void)titleBtnDidClicked
{
    [self reloadSelf];
}

// closeInfiniteView == YES
- (void)setupLeftForFirst
{
    // 刷新第0个tableView
    self.scrollView.contentOffset = CGPointZero;
    UITableView *tableView = self.scrollView.subviews[0];
    self.titleBar.currentPage = 0;
    tableView.tag = self.titleBar.currentPage;
    [tableView reloadData];
}
// closeInfiniteView == YES
- (void)setupRightForLast
{
    // 刷新最后1个tableView
    self.scrollView.contentOffset = CGPointMake(self.jj_width * 2, 0);
    // 这里要设置下 currentPage, 和上面0的时候一样
    self.titleBar.currentPage = self.titleBar.numberOfPages - 1;
    UITableView *tableView = self.scrollView.subviews[2];
    tableView.tag = self.titleBar.currentPage;
    [tableView reloadData];
}

- (void)setupLeftDrawerView
{
    //设置抽屉 view
    if (self.closeInfiniteView) {
        // left
        if (![self.delegate respondsToSelector:@selector(leftDrawerViewWithInfiniteTableView:)]) return;
        UIView *leftDrawerView = [self.delegate leftDrawerViewWithInfiniteTableView:self];
        if ([self.subviews containsObject:leftDrawerView]) {
            return;
        }
        [self insertSubview:leftDrawerView belowSubview:self.scrollView];
        leftDrawerView.frame = CGRectMake(0, 0, leftDrawerView.jj_width, leftDrawerView.jj_height);
        CGFloat leftDrawerWidth = leftDrawerView.jj_width;
        if ([self.delegate respondsToSelector:@selector(widthForLeftDrawerViewWithInfiniteTableView:)]) {
            leftDrawerWidth = [self.delegate widthForLeftDrawerViewWithInfiniteTableView:self];
        }
        if (leftDrawerWidth <= 0) leftDrawerWidth = 0;
        if (leftDrawerWidth >self.jj_width) leftDrawerWidth = self.jj_width;
        self.scrollView.contentInset = UIEdgeInsetsMake(0, leftDrawerWidth, 0, 0);
        self.leftDrawerView = leftDrawerView;
    }
}

- (void)setupRightDrawerView
{
    //设置抽屉 view
    if (self.closeInfiniteView) {
        // right
        if (![self.delegate respondsToSelector:@selector(rightDrawerViewWithInfiniteTableView:)]) return;
        UIView *rightDrawerView = [self.delegate rightDrawerViewWithInfiniteTableView:self];
        if ([self.subviews containsObject:rightDrawerView]) {
            return;
        }
        [self insertSubview:rightDrawerView belowSubview:self.scrollView];
        rightDrawerView.frame = CGRectMake(self.jj_width, 0, rightDrawerView.jj_width, rightDrawerView.jj_height);
        CGFloat rightDrawerWidth = rightDrawerView.jj_width;
        if ([self.delegate respondsToSelector:@selector(widthForRightDrawerViewWithInfiniteTableView:)]) {
            rightDrawerWidth = [self.delegate widthForRightDrawerViewWithInfiniteTableView:self];
        }
        if (rightDrawerWidth <= 0) rightDrawerWidth = 0;
        if (rightDrawerWidth >self.jj_width) rightDrawerWidth = self.jj_width;
        self.scrollView.contentInset = UIEdgeInsetsMake(0, self.scrollView.contentInset.left, 0, rightDrawerWidth);
        self.rightDrawerView = rightDrawerView;
    }
}

- (void)addHudOnScrollView
{
    UIToolbar *toolBar = [[UIToolbar alloc] init];
    toolBar.barStyle = UIBarStyleBlack;
    [self insertSubview:toolBar aboveSubview:self.titleBar];
    toolBar.frame = CGRectMake(self.scrollView.contentInset.left, 0, self.jj_width, self.jj_height);
}

#pragma mark ------------------------------------------
#pragma mark lazy load
- (NSMutableDictionary *)tableViewMemoryContentOffset
{
    if (!_tableViewMemoryContentOffset) {
        _tableViewMemoryContentOffset = [NSMutableDictionary dictionary];
    }
    return _tableViewMemoryContentOffset;
}

#pragma mark ------------------------------------------
#pragma mark set/get

@end
